using System;
using System.Text;
using Castle.MonoRail.Framework;
using Castle.MonoRail.Framework.Services.AjaxProxyGenerator;

namespace Yama.MVC.MonoRail.Services
{
    /// <summary>
    /// A modification od <see cref="Castle.MonoRail.Framework.Services.AjaxProxyGenerator.PrototypeAjaxProxyGenerator"/>
    /// which creates always asynchronous AJAX calls
    /// </summary>
    public class ForceAsyncPrototypeAjaxProxyGenerator : AbstractAjaxProxyGenerator, IAjaxProxyGenerator
    {
        protected override string GenerateJavascriptFunction(string url, string functionName, string httpRequestMethod, ScriptFunctionParameter[] scriptFunctionParameters)
        {
            var function = new StringBuilder();
            function.AppendFormat("\t{0}: function(", functionName);

            var ajaxCallParameters = new StringBuilder();

            for (var i = 0; i < scriptFunctionParameters.Length; i++)
            {
                var scriptFunctionParameter = scriptFunctionParameters[i];
                var clientSideName = scriptFunctionParameter.ClientSideParameterName;
                var serverSideName = scriptFunctionParameter.ServerSideParameterName;

                // append parameters to the function definition
                function.AppendFormat("{0}{1}", clientSideName, i < scriptFunctionParameters.Length - 1 ? ", " : string.Empty);

                // append to the ajax call parameters
                ajaxCallParameters.Append("&")
                    .Append(serverSideName)
                    .Append("='+")
                    .Append(scriptFunctionParameter.NeedsJSONEncoding ? "Object.toJSON(" + clientSideName + ")" : clientSideName)
                    .Append("+'");

                // close the last parameter with an extra "," for the callback parameter
                function.Append(i == scriptFunctionParameters.Length - 1 ? ", " : string.Empty);
            }

            function.Append("callback)").Append(Environment.NewLine).Append("\t{").Append(Environment.NewLine);

            function.AppendFormat("\t\tvar r=new Ajax.Request('{0}', " +
                                 "{{method: '{1}', asynchronous: true, onComplete: callback, parameters: '{2}'}}); " +
                                 Environment.NewLine +
                                 "\t\tif(!callback) return r.transport.responseText;",
                                 url, httpRequestMethod, ajaxCallParameters);

            function.Append("\r\n\t}\r\n");

            return function.ToString();
        }

        string IAjaxProxyGenerator.GenerateJSProxy(IEngineContext context, string proxyName, string area, string controller)
        {
            EnsureServices(context);

            return GenerateJSProxy(context, proxyName, area, controller);
        }

        void EnsureServices(IEngineContext context)
        {
            Service(context.Services);
        }
    }
}